# coding: utf-8

import serial

class MMD1008():
    def __init__(self):
        
        # self.usart_url = 'ftdi://ftdi:2232h/0'
        # self.i2c_url = 'ftdi://ftdi:2232h/1'
        
        self.config_dict = {
            "serial": {
                "port": "COM13",
                "baudrate": 9600,
                "bytesize": 8,
                "parity": 'N',
                "stopbits": 1,
                "xonxoff": False,
                "rtscts": False,
                "timeout": 1,
            }
        }

        self.flag_enquiry_mode = False

        self.command_enquiry_mode = b'\xAA\x00\xFA'
        self.command_get_data = b'\xAA\x00\xF9'
        self.command_reset = b'\xAA\x00\xFE\xBB'
        self.command_decimal = b'\xAA\x00\xFB'
        
        self.configuration()
        
    def __del__(self):
        pass
    
    def configuration(self):
        
        # self.serial = serial_for_url(self.usart_url, **self.config_dict['serial'])
        # self.i2c = I2cController()
        # self.i2c.configure(self.i2c_url)
        
        self.serial = serial.Serial(**self.config_dict['serial'])
        
    def get_gas_data(self):
        
        """
        | 1 byte | 4 bytes     | 4 bytes   | 4 bytes   | 4 bytes   | 1 byte   | 4 bytes  | 1 btye     | 1 byte   |
        |--------|-------------|-----------|-----------|-----------|----------|----------|------------|----------|
        | 0xAA   | temperature | voltage_1 | voltage_2 | voltage_3 | gas type | gas data | warn level | checksum |
        
        NOTE: LSB is used in every 4 bytes data.
        ATTENTION: 甲烷浓度输出不做标定，仅做变化趋势参考，当报警时会固定输出7500的浓度值。
        """
        
        # If the enquiry mode is enabled, then send the command to get data
        if self.flag_enquiry_mode == False:
            self.serial.write(self.command_get_data)
        
        # Read 24 bytes data from the sensor
        data = self.serial.read(24)
        self.data = data
        
        if len(data) != 24:
            return None
        else:
        
            temperature = (data[4] << 24 | data[3] << 16 | data[2] << 8 | data[1]) / 1000
            voltage_1 = (data[8] << 24 | data[7] << 16 | data[6] << 8 | data[5]) / 1000
            voltage_2 = (data[12] << 24 | data[11] << 16 | data[10] << 8 | data[9]) / 1000
            voltage_3 = (data[16] << 24 | data[15] << 16 | data[14] << 8 | data[13]) / 1000
            
            gas_type = data[17]
            gas_data = (data[21] << 24 | data[20] << 16 | data[19] << 8 | data[18]) / 1000
            
            warn_level = data[22]
            
            checksum = data[23]
            
            if self.cal_checksum() != checksum:
                print(checksum, self.cal_checksum())
                return None
            
            return temperature, voltage_1, voltage_2, voltage_3, gas_type, gas_data, warn_level, checksum
        
    def cal_checksum(self):
        '''
        @brief: Calculate the checksum of the data
        '''
        
        checksum = 0
        for i in range(len(self.data) - 1):
            checksum += self.data[i]
        
        return checksum & 0xFF

    def set_enquire_mode(self):
        '''
        @brief: Enable the enquiry mode
        '''
        self.serial.write(self.command_enquiry_mode)
        self.flag_enquiry_mode = True

    def set_reset(self):
        '''
        @brief: Reset the sensor
        '''
        self.serial.write(self.command_reset)
    
    def set_decimal(self):
        '''
        @brief: Switch to output in decimal mode
        '''
        self.serial.write(self.command_decimal)
    
if __name__ == '__main__':
    
    import time
    
    gs = MMD1008()
    
    print("\033[1;31m TEMP \t VOL1 \t VOL2 \tVOL3 \tTYPE \t PPM \tWARN \tCHS\033[0m")
    while True:
        result = gs.get_gas_data()
        if result != None:
            print("%.3f\t%.3f\t%.3f\t%.3f\t%d\t%.3f\t%d\t%d" % result)
        
        time.sleep(1)